package com.cheetah.start.common.aspect;


import cn.hutool.core.util.IdUtil;
import com.cheetah.start.common.utils.IpUtil;
import com.cheetah.start.common.utils.ServletUtil;
import lombok.extern.slf4j.Slf4j;
import net.dreamlu.mica.core.utils.ThreadLocalUtil;
import net.dreamlu.mica.ip2region.core.Ip2regionSearcher;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

/**
 * 控制台记录所有接口请求
 *
 * @author xjhmwj
 * @date 2021/1/25 14:12
 */
@Aspect
@Component
@Slf4j
public class ConsoleLogAspect {

    @Autowired
    private Ip2regionSearcher regionSearcher;

    @Pointcut("execution(public * com.cheetah.start..*.controller..*.*(..))")
    public void webLog() {
    }

    @Before("webLog()")
    public void doBefore(JoinPoint joinPoint) {
    }

    @AfterThrowing(throwing = "e", pointcut = "webLog()")
    public void afterThrow(Throwable e) {
        long start = System.currentTimeMillis();
        ThreadLocalUtil.put("start", start);
        ThreadLocalUtil.put("exception", true);
        MDC.put("logTrackId", IdUtil.simpleUUID().substring(0, 6));
        consoleLog(null, start, true);
    }

    @AfterReturning(returning = "ret", pointcut = "webLog()")
    public void doAfterReturning(Object ret) {
    }

    @Around("webLog()")
    public Object timing(ProceedingJoinPoint joinPoint) throws Throwable {
        Object object;
        long start = System.currentTimeMillis();
        ThreadLocalUtil.put("start", start);
        ThreadLocalUtil.put("exception", false);
        MDC.put("logTrackId", IdUtil.simpleUUID().substring(0, 6));
        object = joinPoint.proceed();
        consoleLog(object, start, false);
        return object;
    }

    private void consoleLog(Object result, long start, boolean afterException) {
        long costTime = System.currentTimeMillis() - start;
        HttpServletRequest request = ServletUtil.getRequest();
        String param = ServletUtil.getParam(request);
        String deviceInfo = ServletUtil.getBrowseInfo(request);

        // 处理完请求，返回内容
        StringBuilder resStr = new StringBuilder();
        if (result != null) {
            resStr.append(result);
            // 给太长的内容截取掉,日志太长不好看
            if (resStr.length() > 500) {
                resStr.delete(500, resStr.length() - 1);
                resStr.append(".....已截取");
            }
        }
        long nanoTime = System.nanoTime();
        String ip = IpUtil.getIpNotHavePort(request);
        String ipPlace = regionSearcher.getAddress(ip);

        if (afterException) {
            log.warn("\n┏━━━━━ 接口地址:[{}],\n┣ 请求方式:[{}],\n┣ 参数:{}\n┣ IP地址:[{}]\n┣ 其他信息:[{}]",
                    request.getRequestURI(),
                    request.getMethod() + "|" + request.getContentType(),
                    param,
                    ip + "|" + ipPlace,
                    deviceInfo
            );
        } else {
            log.info("\n┏━━━━━ 接口地址:{}\n┣ 方式:{}\n┣ 参数:{}\n┣ IP:{}\n┣ 其他:{}\n┣ 接口耗时:{}ms\n┣ 打印耗时:{}μs\n┣ 结果:{}\n┗━━━━━ ",
                    request.getRequestURI(),
                    request.getMethod() + "|" + request.getContentType(),
                    param,
                    ip + "|" + ipPlace,
                    deviceInfo,
                    costTime,
                    (System.nanoTime() - nanoTime) / 1000,
                    resStr);
        }

    }


}
